package liming.tool.json;

import liming.tool.json.annotation.JsonMark;
import liming.tool.json.annotation.JsonPermission;
import liming.tool.json.annotation.JsonType;
import liming.tool.runnable.HandRunnable;

import java.lang.reflect.Field;
import java.util.Map;

class Tool {
    public static String getName(JsonMark annotation, String defaultValue){
        return annotation != null && !annotation.value().isEmpty()?annotation.value():defaultValue;
    }
    public static Class<?> getClassType(JsonType annotation, Class<?> defaultValue){
        return annotation != null && annotation.value()!=null?annotation.value():defaultValue;
    }
    public static Object getFieldValue(Field field, Object obj){
        Object value = HandRunnable.run(() -> {
            try {
                if (!field.isAccessible())
                    field.setAccessible(true);
                return field.get(obj);
            } finally {
                field.setAccessible(false);
            }
        });
        if(value == null&&field.isAnnotationPresent(JsonMark.class)&&isPermission(field.getAnnotation(JsonMark.class).permissions(), JsonPermission.AutoValue))
            return ValueOf.getDefault(field.getType());
        return value;
    }

    public static void setFieldValue(Field field, Object obj, Object value){
        HandRunnable.run(() -> {
            try {
                if (!field.isAccessible())
                    field.setAccessible(true);
                field.set(obj, value);
            } finally {
                field.setAccessible(false);
            }
        });
    }

    public static boolean isPermission(JsonPermission[] permissions, JsonPermission permission){
        if(permission == JsonPermission.None)
            return false;
        for (JsonPermission p : permissions) {
            if (p == permission)
                return true;
            if(p == JsonPermission.All)
                return true;
        }
        return false;
    }

    public static boolean isWrapperType(Class<?> needType) {
        return needType.isPrimitive() || needType.isEnum() ||
                needType.isAssignableFrom(String.class) ||
                needType.isAssignableFrom(Number.class) ||
                needType.isAssignableFrom(Boolean.class);
    }
}
